#include "precompiled.h"
#include "UI_Manager.h"
#include <Awesomium/awesomium_capi.h>
#include <Awesomium/WebView.h>
#include <stdio.h>

#include <string>

using namespace std;

//#define URL "http://newgrounds.com"
#define URL "http://127.0.0.1:8888/"
#define BASEPATH "../UI"
#define UI_INDEX "index.html"
#define UI_HTML "Hello World!</p>"

#define BUFFER_LEN_CALLBACKS 100

#define NAME_UIOBJ_INDEX "Index"
#define NAME_UICALL_INDEX "Callback"

// Manage our callback information and act accordingly.
void HandleCallback(string obj, string callback){
	// Handle index page.
	if(obj == NAME_UIOBJ_INDEX && callback == NAME_UICALL_INDEX){
		printf("The index test button was pressed...\n");
	}
}

void callback_IndexIsReady(awe_webview* view){
	printf("UI: Index loaded...\n");
}

// Respond to UI javascript object events.
void callback_UI(awe_webview* view, awe_string const* object_name, awe_string const* callback_name,
	awe_jsarray const* args){

		char buff_object_name[BUFFER_LEN_CALLBACKS] = {0};
		char buff_callback_name[BUFFER_LEN_CALLBACKS] = {0};
		//char buff_args[BUFFER_LEN_CALLBACKS] = {0};

		// Get the strings.
		awe_string_to_utf8(object_name, buff_object_name, BUFFER_LEN_CALLBACKS);
		awe_string_to_utf8(callback_name, buff_callback_name, BUFFER_LEN_CALLBACKS);

		string s_obj_name(buff_object_name);
		string s_call_name(buff_callback_name);

		HandleCallback( s_obj_name, s_obj_name );
}
void callback_console_UI(awe_webview* view, awe_string const* msg, int line_num, awe_string const* src){

	char buff_msg[BUFFER_LEN_CALLBACKS] = {0};
	char buff_src[BUFFER_LEN_CALLBACKS] = {0};

	// Get the strings.
	awe_string_to_utf8(msg, buff_msg, BUFFER_LEN_CALLBACKS);
	awe_string_to_utf8(src, buff_src, BUFFER_LEN_CALLBACKS);

	printf("UI Javascript Error on line number %d: [%s] from source [%s].\n",line_num,buff_msg,buff_src);
}

void create_uiobject(awe_webview* view, char* name){
	awe_string* awes_name = awe_string_create_from_ascii(name, sizeof(name));
	awe_webview_create_object(view, awes_name);
	awe_string_destroy(awes_name);
}

void create_uicallback(awe_webview* view,  char* name, char* callback){
	awe_string* awes_name = awe_string_create_from_ascii(name, sizeof(name));
	awe_string* awes_callback = awe_string_create_from_ascii(
		callback,sizeof(callback));
	awe_webview_set_object_callback(view, awes_name, awes_callback);
	awe_string_destroy(awes_name);
	awe_string_destroy(awes_callback);

	// Set our UI callback to let the javascript talk to our program.
	awe_webview_set_callback_js_callback(view, callback_UI);
}

void setup_javascript_objects(awe_webview* view){
	// Create our object names.
	create_uiobject(view,NAME_UIOBJ_INDEX);

	// Create our object callbacks.
	create_uicallback(view, NAME_UIOBJ_INDEX, NAME_UICALL_INDEX);

	awe_webview_set_callback_js_console_message(view, callback_console_UI);

	// Create our object properties.
	/*awe_string* property_index_goto_index = awe_string_create_from_ascii(
		"goto_index",sizeof("goto_index"));

	// Create our object property values.
	awe_jsvalue* value_index_goto_index = awe_jsvalue_create_integer_value( 0 );

	// Set object properties.
	awe_webview_set_object_property(view, name_index, 
		property_index_goto_index, value_index_goto_index);*/

}

void display_Basepath(){

	// Check the basepath.
	char basebuff[100] = {0};
	const awe_string* chkstr = awe_webcore_get_base_directory();
	awe_string_to_utf8(chkstr,basebuff,100);
	printf("base: %s",basebuff);

}

UI_Manager::UI_Manager(int width, int height)
{
	// Set our Aweomium width and height.
	ui_width = (width < 0)?default_width:width;
	ui_height = (height < 0)?default_height:height;

	// Initialize.
	init_Awesomium();

	init_UI_Local();
	setup_javascript_objects(ui_webView);
}

UI_Manager::~UI_Manager(void)
{
	cleanup_Awesomium();
}

void UI_Manager::init_Awesomium(){
	/*
	enable_plugins              = false
	enable_javascript           = true
	enable_databases            = false
	package_path                = awe_string_empty()
	locale_path                 = awe_string_empty()
	user_data_path              = awe_string_empty()
	plugin_path                 = awe_string_empty()
	log_path                    = awe_string_empty()
	log_level                   = AWE_LL_NORMAL
	forceSingleProcess          = false
	childProcessPath            = (empty)
	enable_auto_detect_encoding = true
	accept_language_override    = awe_string_empty()
	default_charset_override    = awe_string_empty()
	user_agent_override         = awe_string_empty()
	proxy_server                = awe_string_empty()
	proxy_config_script         = awe_string_empty()
	save_cache_and_cookies      = true
	max_cache_size              = 0
	disable_same_origin_policy  = false
	disable_win_message_pump    = false
	custom_css                  = awe_string_empty()
	 */
	awe_webcore_initialize(true,true,false,awe_string_empty(),awe_string_empty(),awe_string_empty(),awe_string_empty(),awe_string_empty(),AWE_LL_NORMAL,
		false, awe_string_empty(), true, awe_string_empty(),awe_string_empty(),awe_string_empty(),awe_string_empty(),awe_string_empty(),awe_string_empty(),
		true,0,false,false,awe_string_empty());
	ui_webView = awe_webcore_create_webview(ui_width, ui_height, false);

	

	awe_webview_set_transparent(ui_webView, TRUE);
}

void UI_Manager::init_UI_Local(){
	// Set the base path of our html.
	awe_string* astr = awe_string_create_from_ascii(BASEPATH, strlen(BASEPATH));
	awe_webcore_set_base_directory(astr);
	awe_string_destroy(astr);


	// Load the index.
	awe_string* bstr = awe_string_create_from_ascii(UI_INDEX, strlen(UI_INDEX));
	awe_webview_load_file(ui_webView, bstr, awe_string_empty());
	awe_string_destroy(bstr);

	// Set a callback to alert us when the index is loaded.
	//awe_webview_set_callback_finish_loading(ui_webView,callback_IndexIsReady);
}
void UI_Manager::init_UI_URL(){

	awe_string* urlstr = awe_string_create_from_ascii(URL, strlen(URL));
	awe_webview_load_url(ui_webView,urlstr,awe_string_empty(),awe_string_empty(),awe_string_empty());
	awe_string_destroy(urlstr);

}

void UI_Manager::cleanup_Awesomium(){
	awe_webview_destroy(ui_webView);
	awe_webcore_shutdown();
}

void UI_Manager::UpdateDraw(){

	// Update/Draw our UI.
	awe_webcore_update();
	const awe_renderbuffer *ui_buffer = awe_webview_render(ui_webView);

	// Flip image vertically
	unsigned char* imgdata = (unsigned char*)malloc(sizeof(unsigned char) * 4 * ui_width * ui_height);
	awe_renderbuffer_copy_to(ui_buffer,imgdata,awe_renderbuffer_get_rowspan(ui_buffer),4,false,true);
	if( ui_buffer ){
		// Draw pixels directly to screen from our image buffer
		glDrawPixels(ui_width, ui_height, GL_BGRA, GL_UNSIGNED_BYTE, 
			//awe_renderbuffer_get_buffer(ui_buffer));   
			imgdata);
	}
	delete[] imgdata;

}

void UI_Manager::GetInput(){

	// Give our Awesomium UI the latest mouse coordinates.
	glfwGetMousePos(&mousePos.x,&mousePos.y);
	awe_webview_inject_mouse_move(ui_webView, mousePos.x,mousePos.y);
	// Give our Awesomium UI our mouse down events.
	if( glfwGetMouseButton((GLFW_MOUSE_BUTTON_LEFT)) ){
		awe_webview_inject_mouse_down(ui_webView, awe_mousebutton::AWE_MB_LEFT);
		awe_webview_inject_mouse_up(ui_webView, awe_mousebutton::AWE_MB_LEFT);
	}
}

void UI_Manager::manage_callbacks(){
	// Awesomium C does this synchronously. Awesomium
	// is not thread safe. What we can do is maintain an asynch Q. This is a queue
	// that is always available to have stuff pushed into. We can just pop off values
	// whenever we like.
	// See: http://support.awesomium.com/discussions/questions/620-implementing-futures-for-c-api.
	// 
	// Note that each queue object should have a string value and an id key. key-value ftw. The
	// id will denote what function we are getting a result from. For instance a UI button to
	// go to stage select could have id-7 and key-a. This information should all exist in an
	// automated system that does stuff like "register_callback_result(int id, std::string key)"
	// to minimize human fudging/error.
	//	
	// awe_webview_set_callback_js_callback.
	// awe_webview_execute_javascript_with_result.
}